package com.nine.mq.customer;

import com.nine.mq.config.constanst.MqConstanst;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.*;

import java.util.Map;

@Slf4j
//@Component
public class DirectConsumer {

    /**
     * 接收消息的方法
     *
     * @param message
     */
    //@RabbitHandler
    //@RabbitListener(queues = MqConstanst.QUEUE_NAME)
    public void receive(String message) {
        System.out.println("DirectConsumer 接收到消息：" + message);
    }


    /**
     * queues() 属性用于指定需要监听的队列名称，如 queues="queueName"，它会从默认的 Exchange 中绑定到指定的队列，并监听该队列中的消息。
     * queuesToDeclare() 属性用于在监听之前声明队列对象，如果该队列不存在则会自动创建，
     *  如 queuesToDeclare = @Queue("queueName")，它会声明一个名为 queueName 的队列对象，并将其绑定到默认的 exchange 中，然后监听该队列中的消息。
     * 因此，queues() 属性用于监听已经存在的队列，而 queuesToDeclare() 属性则可以同时声明并监听一个队列。
     * @param map
     * @param channel
     * @param message
     */
    @RabbitHandler
    @RabbitListener(bindings = {
            @QueueBinding(
                    // 队列，如果不指定队列名称，默认会创建一个临时队列，用完会自动删除
                    value = @Queue(name = MqConstanst.QUEUE_NAME, durable = "true"),
                    // 交换机
                    exchange = @Exchange(name = MqConstanst.EXCHANGE_NAME, durable = "true", type = "direct"),
                    // 路由键
                    key = {MqConstanst.ROUTING_KEY})
    })
    public void receiveMsg(Map map, Channel channel, Message message) {
        log.info("DirectConsumer02 接收到消息[map]: {}", map.toString());
        try {
            String msg = new String(message.getBody(), "UTF-8");
            log.info("DirectConsumer02 接收到消息[message]: {}", msg);

            // 手动确认消息已被消费
            // 由于设置了手动确认，所以需要手动发送ack，注意：如果设置了自动应答，这里又进行手动应答，会出现double ack
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


}
